use serde::{Deserialize, Serialize};
use sqlx::{sqlite::SqliteRow, Row};

use crate::utils::{cache_util, mysql_utils::get_connect};

lazy_static::lazy_static! {
    pub static ref DIC_KEY: String = String::from("dic_key");
}

#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Config {
    pub id: String,
    pub dic_path: String,
    pub gitee: String,
    pub create_time: i64,
    pub creator_lid: String,
    pub creator_name: String,
    pub updater_lid: String,
    pub updater_name: String,
    pub up_ver: i16,
    pub sort: i16,
    pub tenant_id: i64,
    pub deleted: i64,
    pub update_time: i64,
}

impl Default for Config {
    fn default() -> Self {
        Config{
            id: "0".to_string(),
            dic_path: String::from(""),
            gitee: String::from(""),
            create_time: 0,
            creator_lid: String::from(""),
            creator_name: String::from(""),
            updater_lid: String::from(""),
            updater_name: String::from(""),
            up_ver: 0,
            sort: -1,
            tenant_id: 0,
            deleted: 0,
            update_time: 0,
        }
    }
}

pub async fn get_config() -> Option<Config> {
    let mut conn = get_connect()
        .acquire()
        .await
        .expect("Error get_connect from db pool");
    let rust = sqlx::query(
        "select id, dic_path, gitee from config where id = 1",
    )
    .map(|row: SqliteRow| {
        let mut config = Config::default();
        config.id = row.get(0);
        config.dic_path = row.get(1);
        config.gitee = row.get(2);
        config
    })
    .fetch_all(&mut *conn)
    .await;
    match rust {
        Ok(rest) => {
            if let Some(res) = rest.get(0) {
                return Some(res.clone());
            }
            return None;
        }
        Err(e) => {
            log::info!("get_info_by_id失败{}", e);
            return None;
        }
    }
}


pub async fn up_config(dic_path: String, gitee: String) -> bool {
    let mut conn = get_connect()
        .acquire()
        .await
        .expect("Error get_connect from db pool");
    let result = sqlx::query(
        "update config set dic_path = ?, gitee = ? where id = 1",
    )
    .bind(dic_path)
    .bind(gitee)
    .execute(&mut *conn)
    .await;
    match result {
        Ok(_) => {
            log::info!("更新数据成功");
            return true;
        }
        Err(e) => {
            log::info!("{}", e);
            log::info!("更新数据失败");
            return false;
        }
    }
}

#[tokio::main]
pub async fn get_dic_path_tokio() -> Option<String> {
    get_dic_path().await
}

pub async fn get_dic_path() -> Option<String> {
    let dic_path: Option<String> = cache_util::get_cache_(&DIC_KEY).await;
    match dic_path {
        Some(path) => {
            return Some(path);
        },
        None => {
            let result = get_config().await;
            match result {
                Some(config) => {
                    if config.dic_path.is_empty() {
                        return None
                    }
                    cache_util::set_cache_(DIC_KEY.to_string(), config.dic_path.clone(), None).await;
                    return Some(config.dic_path);
                },
                None => return None,
            }
        },
    }
}

#[tokio::main]
pub async fn up_dir_config_tokio(dic_path: String) -> bool {
    up_dir_config(dic_path).await
}

pub async fn up_dir_config(dic_path: String) -> bool {
    let mut conn = get_connect()
        .acquire()
        .await
        .expect("Error get_connect from db pool");
    let result = sqlx::query(
        "update config set dic_path = ? where id = 1",
    )
    .bind(dic_path)
    .execute(&mut *conn)
    .await;
    match result {
        Ok(_) => {
            log::info!("更新数据成功");
            return true;
        }
        Err(e) => {
            log::info!("{}", e);
            log::info!("更新数据失败");
            return false;
        }
    }
}